package org.common.utils.rpc.core;
import com.esotericsoftware.reflectasm.MethodAccess;
import org.common.utils.rpc.exception.RpcInterfaceImplementException;
import org.common.utils.tool.ClassTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * RPCServer中实现接口的对象池
 * @author zhouzhibing
 * @date 2025/11/18 13:14
 */
public class RpcImplementPool {

    private static final Logger log = LoggerFactory.getLogger(RpcImplementPool.class);

    /**
     * 实现对象列表<接口类，<方法名，实现方法对象>>
     */
    private final Map<Class<?>, Map<String , RpcMethodImpl>> implementMap = new ConcurrentHashMap<>();

    public RpcImplementPool(String packageName) {
        initImplement(packageName);
    }

    /**
     * 初始化RPC实现对象
     * @param packageName 包名
     */
    private void initImplement(String packageName) {
        Set<Class<?>> allClass = ClassTool.getAllClass(packageName);

        Class<?> currentClass = null;
        Method currentMethod = null;

        try {
            for (Class<?> clazz : allClass) {
                if (clazz.isInterface()) {
                    RpcInterface rpcInterface = clazz.getAnnotation(RpcInterface.class);
                    //不是RpcInterface接口
                    if(rpcInterface == null) {
                        continue;
                    }

                    //该RPC接口下所实现的类，且仅只有一个实现。
                    Set<Class<?>> allSubClass = ClassTool.getAllSubClass(packageName, clazz);
                    if(allSubClass.size() != 1) {
                        throw new RpcInterfaceImplementException();
                    }

                    Class<?> implementClass = allSubClass.iterator().next();
                    currentClass = implementClass;

                    Object instance = implementClass.newInstance();
                    MethodAccess methodAccess = MethodAccess.get(implementClass);
                    Map<String, RpcMethodImpl> methodInstanceMap = implementMap.get(clazz);
                    if(methodInstanceMap == null) {
                        methodInstanceMap = new ConcurrentHashMap<>();
                        implementMap.put(clazz, methodInstanceMap);
                    }

                    for (Method method : implementClass.getDeclaredMethods()) {
                        currentMethod = method;
                        if (Modifier.isPublic(method.getModifiers())) {
                            methodInstanceMap.put(method.getName(), new RpcMethodImpl(instance, methodAccess, method));
                        }
                    }
                }
                log.info("initImplement success , clazz = {}" , clazz);
            }
        } catch (Exception e) {
            log.error("initImplement error , currentClass = {} , currentMethod = {}" , currentClass , currentMethod , e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取RPC实现方法对象
     * @param clazz 接口类
     * @param methodName 方法名
     * @return RPC实现方法对象
     */
    public RpcMethodImpl getRpcMethodImpl(Class<?> clazz , String methodName) {
        Map<String, RpcMethodImpl> methodInstanceMap = implementMap.get(clazz);
        if(methodInstanceMap == null) {
            return null;
        }
        return methodInstanceMap.get(methodName);
    }

    /**
     * 调用RPC实现方法
     * @param clazz 接口类
     * @param methodName 方法名
     * @param args 参数
     * @return 方法返回值
     */
    public Object invoke(Class<?> clazz , String methodName , Object[] args) {
        RpcMethodImpl methodImpl = getRpcMethodImpl(clazz , methodName);
        return methodImpl.invoke(args);
    }
}
